/*
 * defination of slab allocator
 */

#ifndef MM_H_
#define MM_H_

#include <stdbool.h>

// ----------------------------------------------------------------------
// something global
// ----------------------------------------------------------------------

#define PAGE_SIZE 4096
#define L1_CACHE_LINE_BYTES_X86  32     // warnning: this may be incorrect!
#define L1_CACHE_LINE_BYTES_IA64 32     // warnning: this may be incorrect!
#define RECYCLE_CACHE_CHAIN_LEN  100    // when we do recycle, the maximum caches we'll travel through
#define RECYCLE_THRESHOLD        1000   // if we currently use more than this many pages, we try to recycle some memory

extern int page_occupied; //total number of pages allocated

struct list_head
{
    struct list_head *next, *prev;
};

typedef struct mem_cache_s
{
    struct list_head next; // pointer to the next and prev mem_cache_t
    struct list_head slabs_full;
    struct list_head slabs_partial;
    struct list_head slabs_free;
    unsigned int     objsize;
    unsigned int     objnum;
    unsigned int     pagenum;
    int              colour;
    unsigned int     colour_off;
    unsigned int     colour_next;
    void             (*ctor)(void*, struct mem_cache_s*, unsigned int);
    void             (*dtor)(void*, struct mem_cache_s*, unsigned int);

} mem_cache_t;

typedef struct cache_sizes
{
    int           cs_size;
    mem_cache_t*  cs_cachep;
} cache_sizes_t;

extern cache_sizes_t cache_sizes[];

// ----------------------------------------------------------------------
// most important routines
// ----------------------------------------------------------------------

// system init and de-init routines

extern bool mm_enable_rec;

bool mm_init(bool enable_rec);

bool mm_deinit();

// main routines for use

void* mm_malloc(int size);

void mm_free(void* objp);

// ----------------------------------------------------------------------
// cache level functions and variables
// ----------------------------------------------------------------------

extern mem_cache_t cache_cache;
extern mem_cache_t* next_rec_cachep;
extern struct list_head cache_list_head;
extern int cur_cache_count;

// some cache level functions

mem_cache_t* mem_cache_create
    (int size, unsigned int flags, void (*ctor)(void*, mem_cache_t*, unsigned int), void (*dtor)(void*, mem_cache_t*, unsigned int));

int mem_cache_recycle();

int mem_shrink(mem_cache_t* cachep);

int mem_cache_destory(mem_cache_t* cachep);

// ----------------------------------------------------------------------
// slab level functions and variables
// ----------------------------------------------------------------------

typedef unsigned int mem_bufctl_t;

#define BUFCTL_END      (((mem_bufctl_t)(~0U))-0)

typedef struct slab_s
{
    struct list_head list;
    mem_cache_t *cache_masterp;
    unsigned int colouroff;
    void *s_mem;
    unsigned int inuse;
    mem_bufctl_t free;
} slab_t;

void* mem_cache_alloc(mem_cache_t *cachep);
void mem_cache_free(mem_cache_t *cachep, void *objp);

slab_t * slab_create(mem_cache_t *cachep);
void slab_init(mem_cache_t *cachep, slab_t *slabp);
unsigned int slab_destroy(mem_cache_t *cachep, slab_t *slabp);

void addto_listhead(struct list_head *list, slab_t *slabp);
void addto_listtail(struct list_head *list, slab_t *slabp);
void delfrom_list(struct list_head *list, slab_t *slabp);

#endif /* MM_H_ */
